﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace cstdx.Internal;

public static class NumberConverter
{
	/// <summary>
	/// 判断double是否为NaN或无穷大
	/// </summary>
	/// <param name="f">要检查的double值</param>
	/// <returns>如果是NaN或无穷大则返回true，否则返回false</returns>
	public static bool Float64IsNaN(double f)
	{
		return double.IsNaN(f) || double.IsInfinity(f);
	}

	/// <summary>
	/// 将指定的数值类型转换为double
	/// </summary>
	/// <typeparam name="T">支持的类型：ushort, uint, float</typeparam>
	/// <param name="v">要转换的值</param>
	/// <returns>转换后的double值</returns>
	public static double NumberToFloat64<T>(T v) where T : struct
	{
		// 约束T为ushort, uint或float
		if (typeof(T) != typeof(ushort) && typeof(T) != typeof(uint) && typeof(T) != typeof(float))
		{
			throw new ArgumentException("不支持的类型，仅支持ushort, uint, float");
		}

		return Convert.ToDouble(v);
	}

	/// <summary>
	/// 将整型转换为double
	/// </summary>
	/// <typeparam name="T">支持的类型：uint, int, long及其别名类型</typeparam>
	/// <param name="integer">要转换的整数值</param>
	/// <returns>转换后的double值</returns>
	public static double IntToFloat64<T>(T integer) where T : struct, IConvertible
	{
		// 将输入转换为int（对应Go中的int类型处理）
		int ivol = integer.ToInt32(null);

		// 提取各个位段
		int logPoint = ivol >> (8 * 3);
		int hleax = (ivol >> (8 * 2)) & 0xff;
		int lheax = (ivol >> 8) & 0xff;
		int lleax = ivol & 0xff;

		// 计算各个偏移值
		int dwEcx = logPoint * 2 - 0x7f;
		int dwEdx = logPoint * 2 - 0x86;
		int dwEsi = logPoint * 2 - 0x8e;
		int dwEax = logPoint * 2 - 0x96;

		// 计算dblXmm6
		int tmpEax = dwEcx < 0 ? -dwEcx : dwEcx;
		double dblXmm6 = Math.Pow(2.0, tmpEax);
		if (dwEcx < 0)
		{
			dblXmm6 = 1.0 / dblXmm6;
		}

		// 计算dblXmm4
		double dblXmm4 = 0.0;
		if (hleax > 0x80)
		{
			int dwtmpeax = dwEdx + 1;
			double tmpdblXmm3 = Math.Pow(2.0, dwtmpeax);
			double dblXmm0 = Math.Pow(2.0, dwEdx) * 128.0;
			dblXmm0 += (hleax & 0x7f) * tmpdblXmm3;
			dblXmm4 = dblXmm0;
		}
		else
		{
			double dblXmm0 = 0.0;
			if (dwEdx >= 0)
			{
				dblXmm0 = Math.Pow(2.0, dwEdx) * hleax;
			}
			else
			{
				dblXmm0 = (1 / Math.Pow(2.0, -dwEdx)) * hleax;
			}
			dblXmm4 = dblXmm0;
		}

		// 计算dblXmm3和dblXmm1
		double dblXmm3 = Math.Pow(2.0, dwEsi) * lheax;
		double dblXmm1 = Math.Pow(2.0, dwEax) * lleax;

		// 根据hleax的0x80位进行调整
		if ((hleax & 0x80) != 0)
		{
			dblXmm3 *= 2.0;
			dblXmm1 *= 2.0;
		}

		// 返回总和
		return dblXmm6 + dblXmm4 + dblXmm3 + dblXmm1;
	}
}


